package dev.ece.suit.loader.models.dae;

import dev.ece.suit.loader.Joint;
import dev.ece.util.lib.Matrix4f;

public class DAEJoint implements Joint<Float> {

	private String name;
	
	private DAEJoint parent;
	
	private Matrix4f finalMatrix;
	private Matrix4f normalMatrix = new Matrix4f();
	
	private Matrix4f offsetMatrix = new Matrix4f();
	private Matrix4f globalMatrix = new Matrix4f();
	
	private DAEKeyFrame[] keyFrames;
	
	public DAEJoint(String name, float[] skeleton, DAEJoint parent) {
		this.name = name;
		this.finalMatrix = new Matrix4f(skeleton);
		this.parent = parent;
	}
	
	protected void setup() {
		if(this.offsetMatrix == null) {
			this.offsetMatrix = new Matrix4f();
			this.offsetMatrix.identity();
		}
		this.getNormalTransform().set(this.getFinalTransform());
		this.getNormalTransform().invert().transpose();
	}
	
	@Override
	public boolean hasKeyFrames() {
		return this.keyFrames != null;
	}

	@Override
	public Joint<Float> getParent() {
		return parent;
	}

	@Override
	public String getName() {
		return name;
	}

	public DAEKeyFrame[] getKeyFrames() {
		return keyFrames;
	}

	public void setKeyFrames(DAEKeyFrame[] keyFrames) {
		this.keyFrames = keyFrames;
	}

	@Override
	public Matrix4f getLocalTransform(Float current) {
		DAEKeyFrame end = null;
		DAEKeyFrame start = null;
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		for(int i=0; i<this.keyFrames.length; i++) {
			if(current <= this.keyFrames[i].getTime()) {
				end = this.keyFrames[i];
				if(i > 0) {
					start = this.keyFrames[i - 1];
				}
				break;
			}
		}
		if(end == null) {
			start = this.keyFrames[this.keyFrames.length - 1];
		}
		float alpha = 0;
		if(end == null) {
			return start.getMatrix();
		}
		if(start == null) {
			alpha = current / end.getTime();
			Matrix4f left = new Matrix4f();
			left.identity();
			return Matrix4f.interpolate(left, end.getMatrix(), alpha);
		}
		alpha = (current - start.getTime()) / (end.getTime() - start.getTime());
		return Matrix4f.interpolate(start.getMatrix(), end.getMatrix(), alpha);
	}

	@Override
	public Matrix4f getGlobalTransform() {
		return globalMatrix;
	}

	public void setOffsetMatrix(Matrix4f offsetMatrix) {
		this.offsetMatrix = offsetMatrix;
	}

	@Override
	public Matrix4f getOffsetTransform() {
		return offsetMatrix;
	}

	@Override
	public Matrix4f getFinalTransform() {
		return finalMatrix;
	}

	@Override
	public Matrix4f getNormalTransform() {
		return normalMatrix;
	}

}
